﻿using System;
using System.Data;
using System.Data.Common;
using Dapper;
using ProjetoSolo.QueroGas.Dominio.Repositorios;
using ProjetoSolo.QueroGas.Infraestrutura.PersistenciaAdo.Util;

namespace ProjetoSolo.QueroGas.Infraestrutura.PersistenciaAdo
{
    public class ContextoAdo : IContextoRepositorio
    {
        private DbConnection conexaoBanco;
        private IDbTransaction transacao;
        private readonly string nomeStringConexao;

        public ContextoAdo(string nomeStringConexao)
        {
            this.nomeStringConexao = nomeStringConexao;
        }

        public IDbConnection Conexao
        {
            get { return this.conexaoBanco ?? (this.conexaoBanco = FabricaConexao.CriarConexao(this.nomeStringConexao)); }            
        }

        public IDbTransaction Transacao()
        {
            this.AbrirTransacao();

            return this.transacao;
        }

        public IDbCommand CriarComandoBanco()
        {           
            this.IniciarConexao();
            this.AbrirTransacao();

            IDbCommand comando = this.conexaoBanco.CreateCommand();
            
            if(comando.Transaction == null)
                comando.Transaction = this.transacao;

            return comando;
        }       

        public void PersistirAlteracoes()
        {
            this.VerificarEstadoTransacao();
            this.transacao.Commit();

            this.transacao = null;
        }

        public void DescartarAlteracoes()
        {
            if(transacao != null)
                this.transacao.Rollback();
        }

        public void Dispose()
        {
            if (this.transacao != null)
                this.transacao.Dispose();

            if (this.conexaoBanco != null)
            {
                this.conexaoBanco.Dispose();
                this.conexaoBanco = null;
            }
        }

        private void IniciarConexao()
        {
            if (this.conexaoBanco == null)
                this.conexaoBanco = FabricaConexao.CriarConexao(this.nomeStringConexao);

            if (this.conexaoBanco.State != ConnectionState.Open)
            {
                this.conexaoBanco.Open();
            }
        }

        private void AbrirTransacao()
        {
            if(this.transacao != null)
                return;

            if(this.conexaoBanco == null)
                return;            
            
            if(this.conexaoBanco.State != ConnectionState.Open)
            {
                this.conexaoBanco.Open();
                this.transacao = conexaoBanco.BeginTransaction();
            }
        }

        private void VerificarEstadoTransacao()
        {
            if(this.transacao == null)
                throw new InvalidOperationException("A transação está fechada.");
        }
    }
}
